package no.ntnu.fp.server;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import no.ntnu.fp.model.Appointment.RSVP;
import no.ntnu.fp.model.Message;
import no.ntnu.fp.model.AbstractModel;
import no.ntnu.fp.model.Appointment;
import no.ntnu.fp.model.ModelListener;
import no.ntnu.fp.model.Person;
import no.ntnu.fp.model.Room;
import no.ntnu.fp.model.SuperPackage;
import nu.xom.ParsingException;
import nu.xom.ValidityException;

public class ModelHandler implements Runnable {

	private DBConnection db;

	public ModelHandler() {

		db = new DBConnection();
		initializeModels();
	}

	public void updateModel(String s) {

		nu.xom.Builder parser = new nu.xom.Builder(false);
		nu.xom.Document doc = null;
		try {
			doc = parser.build(s, "");
			SuperPackage sp = new SuperPackage(doc);
			modelChanged(sp.run());

		} catch (ValidityException e) {
		} catch (ParsingException e) {
		} catch (IOException e) {
		} catch (SecurityException e) {
		} catch (IllegalArgumentException e) {
		} catch (ClassNotFoundException e) {
		} catch (NoSuchMethodException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		}
	}

	public void initializeModels() {

		db.selectAll("Person");
		db.selectAll("Appointment");
		db.selectAll("Message");
		db.selectAll("Room");

	}

	public void deleteAllAppointmentToUserAssociations(int id) {

		Appointment a = Appointment.get(id);
		db.deleteFromAppointmentToUser(id);
		
		for (Entry<Integer, RSVP> entry : a.inviteList.entrySet()) {
			Integer personId = entry.getKey();
			RSVP rsvp = entry.getValue();
			db.insertAppointmentToUser(id, personId, rsvp);
		}
	}

	public synchronized void transferModelsToClient(ConnectionHandler c) {

		SuperPackage sp = new SuperPackage();

		for (Room r : Room.all()) {
			sp.put(r);
		}
		for (Person p : Person.all()) {
			sp.put(p);
		}
		for (Appointment a : Appointment.all()) {
			sp.put(a);
		}
		for (Message m : Message.all()) {
			sp.put(m);
		}

		c.send(sp.toDocument().toXML().toString());
	}

	@Override
	public void run() {
	}

	public void modelChanged(List<AbstractModel> models) {

		for (AbstractModel model : models) {

			if (model instanceof Appointment) {
				Appointment a = (Appointment)model;
				if(a.id >= 0) {
					db.updateAppointment(a);
					db.updateAllParticipate(a);
				}
				else {
					db.insertAppointment(a.title, a.type.ordinal(), a.startDate, a.endDate,
							a.start, a.end, a.description, a.guestCount, a.alive, a.place, 
							a.inviteList.keySet(), a.owner);
				}
			} else if (model instanceof Message) {
				Message m = (Message)model;
				if (m.id >= 0) {
					db.updateMessageAllFields(m);
				}
				else {
					db.insertMessage(m.to, m.appointment, m.messageType.ordinal());
				}
			}

		}
	}
}
